package com.tarena.lbs.basic.web.service;

import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.UserRepository;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.UserPO;
import com.tarena.lbs.pojo.passport.param.AdminLoginParam;
import com.tarena.lbs.pojo.passport.param.UserLoginParam;
import com.tarena.lbs.pojo.passport.vo.LoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LoginService {
    //数据层(repository mapper 类型命名习惯 操作哪个表格**Repository **Mapper
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private JwtEncoder jwtEncoder;
    @Autowired
    private UserRepository userRepository;
    //登录业务实现
    //参考 开发代码之前的业务流程图
    public LoginVO doLogin(UserLoginParam param) throws BusinessException {
        //1.使用电话号码检查 是否存在 获取存在的UserPO
        UserPO po=checkAndGetUser(param.getPhone());
        //2.复用后台登录对比密码逻辑
        matchPassword(param.getPassword(),po.getPassword());
        //3.调整generateJWT代码尽量复用
        String jwt = generateJWT(po.getId(), po.getNickName(), Roles.USER);
        //4.封装LoginVO返回
        return new LoginVO(jwt,po.getId(),po.getNickName());
    }

    private UserPO checkAndGetUser(String phone) throws BusinessException {
        //先查 断言 select * from lbs_user where phone=#{}
        QueryWrapper<UserPO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        UserPO po = userRepository.getOne(queryWrapper);
        Asserts.isTrue(po==null,new BusinessException("-2","用户名不存在"));
        return po;
    }

    public LoginVO doLogin(AdminLoginParam param) throws BusinessException {
        //1.查询存在的AdminPO 判断存在
        AdminPO adminPO=checkAndGetAdmin(param.getPhone());
        //2.对比密码 判断对比结果 尽可能做成复用 小程序登录也要对比
        matchPassword(param.getPassword(),adminPO.getAccountPassword());
        //3.生成JWT
        String jwt=generateJWT(adminPO.getId(),adminPO.getNickname(),adminPO.getAccountType()==0?Roles.ADMIN:Roles.SHOP);
        //4.封装vo返回 ID NICKNAME JWT
        return new LoginVO(jwt,adminPO.getId(),adminPO.getNickname());
    }

    private String generateJWT(Integer id,String nickName,Roles role) throws BusinessException {
        //1.存在一个jwt工具类 --JwtEncoder怎么用 配置类管理这个对象
        //2.在jwt携带什么数据 AdminPO(statues,password) 这个po有单独使用场景 数据层,在jwt
        //里携带的数据是专门来做认证的.UserPrinciple
        UserPrinciple userPrinciple=new UserPrinciple();
        userPrinciple.setId(id);
        userPrinciple.setNickname(nickName);
        //封装userPrinciple中需要携带的认证信息 角色
        //角色是系统业务定义 平台管理员Role.ADMIN 商家管理员Role.SHOP 小程序用户Role.USER
        //这个登录 是后台管理员登录 所以不可能有USER角色 ADMIN SHOP 取决于登录admin的type字段
        userPrinciple.setRole(role);
        return jwtEncoder.generateToken(userPrinciple);
    }

    private void matchPassword(String password, String accountPassword) throws BusinessException {
        //严谨一点 应该考虑入参连个值是不是空
        //调用一个现成的工具判断相等
        boolean equals = StringUtils.equals(password, accountPassword);
        //判断 命中条件 抛异常
        Asserts.isTrue(!equals,new BusinessException("-2","密码不正确"));
    }

    private AdminPO checkAndGetAdmin(String phone) throws BusinessException {
        //select * from tarena_lbs_basic.lbs_admin where account_phone=#{phone}
        //mybatis-plus一罐做法中,封装id以外的非主键条件需要使用where条件的拼接对象
        QueryWrapper<AdminPO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("account_phone",phone);
        AdminPO po = adminRepository.getOne(queryWrapper);
        //判断,命中条件 抛异常逻辑,不在写if 写断言Assert
        /*if (po==null){
        //业务异常,自己封装异常逻辑 返回提示信息
            throw new BusinessException("-2","用户名不存在"); 异常属性 对应Result两个值 code message
        }*/
        Asserts.isTrue(po==null,new BusinessException("-2","用户名不存在"));
        return po;
    }
}
